package com.sinevil.tcpTrans.entity.json.handlers;


import com.sinevil.tcpTrans.entity.json.FilePacketJson;
import com.sinevil.tcpTrans.entity.json.InstructionJson;
import com.sinevil.tcpTrans.tcp.TCPClientNode;
import com.sinevil.tcpTrans.tcp.TCPTransNode;
import com.sinevil.tcpTrans.utils.fileTrans.FileTranser;
import lombok.SneakyThrows;

import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.regex.Matcher;

/**
 * @Classname ClientSocketJsonHandle
 * @Description TODO 客户端 套接字维护
 * @Version 1.0.0
 * @Date 2024/12/14 0:48
 * @Created by sinevil
 */
public class ClientSocketJsonHandle extends SocketJsonHandle {
    String uuid;
    protected TCPClientNode clientNode;

    /**
     *
     * @param clientNode 客户端指令结点
     * @param fileTranser 文件传输管理者
     * @param buffer_size 处理消息时缓冲区的大小
     */
    public ClientSocketJsonHandle(TCPClientNode clientNode, FileTranser fileTranser, int buffer_size){
        super();
        this.clientNode = clientNode;
        this.fileTranser = fileTranser;
        this.BUFFER_SIZE = buffer_size;
        this.readBuffer = ByteBuffer.allocate(buffer_size+256);
        this.writeBuffer = ByteBuffer.allocate(buffer_size+256);

        this.initInstructionHandlersMap();
        this.initFilePacketHandlersMap();
    }

    /**
     *  使用TCPTransNode中的默认缓冲区大小
     * @param clientNode 客户端指令结点
     * @param fileTranser 文件传输管理器
     */
    public ClientSocketJsonHandle(TCPClientNode clientNode, FileTranser fileTranser){
        this(clientNode,fileTranser, TCPTransNode.BUFFER_SIZE);

    }


    /**
     * 初始化默认的指令Json数据类对象和处理函数的映射关系
     */
    @Override
    protected void initInstructionHandlersMap(){
        super.initInstructionHandlersMap();
        // 添加共有的指令处理函数
        this.instructionHandlersMap.put(InstructionJson.PUBLIC_FILE_MD5,this::handlePUBLIC_FILE_MD5);

        this.instructionHandlersMap.put(InstructionJson.PUBLIC_FILE_INFO,this::handleSERVER_RECOVER_FILE_INFO);
        this.instructionHandlersMap.put(InstructionJson.PUBLIC_REQUEST_FILE_PACKET,this::handleSERVER_REQUEST_FILE_PACKET);
        this.instructionHandlersMap.put(InstructionJson.PUBLIC_REQUEST_FILE_COMPLETE,this::handleSERVER_REQUEST_FILE_COMPLETE);
        this.instructionHandlersMap.put(InstructionJson.PUBLIC_UPLOAD_ERROR_REQUEST_FILE,this::handlePUBLIC_UPLOAD_ERROR_REQUEST_FILE);

    }

    /**
     * 初始化默认的文件包数据类对象和处理函数的映射关系
     * TODO 对应文件数据包的处理扩展 应更改为针对 数据包json 类型直接获取处理函数，应在JsonHandlersMap中直接添加
     */
    @Override
    protected void initFilePacketHandlersMap() {
        super.initFilePacketHandlersMap();
        // 添加共有的文件数据包处理函数
        this.filePacketHandlersMap.put(FilePacketJson.class,this::handlePUBLIC_ACCEPT_FILE_PACKET);

    }



    /**
     * 客户端 处理 服务端 返回文件信息
     * 请求下载文件时
     * @param instructionJson 服务端返回的文件信息
     */
    @SneakyThrows
    private void handleSERVER_RECOVER_FILE_INFO(InstructionJson instructionJson, SocketChannel socketChannel){
        String content = instructionJson.getContent();
        Matcher matcher = InstructionJson.PUBLIC_FILE_INFO_PATTERN.matcher(content);
        if (matcher.find()){
            String uid = matcher.group(1);
            long size = Long.parseLong(matcher.group(2));
            String fileName= matcher.group(3);
            String path = matcher.group(4);
            if(!fileTranser.addDownloadTask(socketChannel,fileName,uid,size,path)){
                // 添加下载任务失败，则向上传端发送失败信息
                this.clientNode.sendMessage(socketChannel, new InstructionJson(InstructionJson.PUBLIC_REQUEST_FILE_COMPLETE, String.format(InstructionJson.PUBLIC_REQUEST_FILE_COMPLETE_FORMAT, uid, 2, "下载任务启动失败")));
            }
        }
    }




    /**
     * 客户端上传文件时 服务端下载文件完成，通知客户端清理资源
     * 通知客户端清理资源
     * @param instructionJson 下载文件完成指令
     * @param socketChannel 服务端套接字
     */
    private void handleSERVER_REQUEST_FILE_COMPLETE(InstructionJson instructionJson, SocketChannel socketChannel) {
        String content = instructionJson.getContent();
        Matcher matcher = InstructionJson.PUBLIC_REQUEST_FILE_COMPLETE_PATTERN.matcher(content);
        if (matcher.find()) {
            this.fileTranser.completeUploadTrans(socketChannel, matcher.group(1), Integer.parseInt(matcher.group(2)),matcher.group(3));
        }
    }

    /**
     * 客户端 处理 服务端请求文件数据包
     * @param instructionJson 请求数据包指令
     * @param socketChannel 服务端套接字
     */
    private void handleSERVER_REQUEST_FILE_PACKET(InstructionJson instructionJson, SocketChannel socketChannel){
        String content = instructionJson.getContent();
        Matcher matcher = InstructionJson.PUBLIC_REQUEST_FILE_PACKET_PATTERN.matcher(content);
        if (matcher.find()) {
            this.fileTranser.addUploadPacketRequest(socketChannel, matcher.group(1), Long.parseLong(matcher.group(2)),Integer.parseInt(matcher.group(3)));
        }
    }

}